package com.yeskery.nut.cloud.loadbanlancer;

import com.yeskery.nut.cloud.registry.core.Instance;
import com.yeskery.nut.cloud.registry.core.Server;

import java.util.concurrent.TimeUnit;

/**
 * 带有重试的选择器
 * @author YESKERY
 * 2024/1/19
 */
public class RetryChooser implements Chooser {

    /** 最大重试次数 */
    private int maxRetryTimes = 3;

    /** 每次重试的等待时间(毫秒) */
    private long retryWaitTime = 500;

    /** 基础选择器 */
    private final Chooser baseChooser;

    /**
     * 构建带有重试的选择器
     * @param maxRetryTimes 最大重试次数
     * @param retryWaitTime 每次重试的等待时间(毫秒)
     * @param baseChooser 基础选择器
     */
    public RetryChooser(int maxRetryTimes, long retryWaitTime, Chooser baseChooser) {
        if (maxRetryTimes <= 0 || retryWaitTime < 0) {
            throw new IllegalArgumentException("Invalid Parameters.");
        }
        this.maxRetryTimes = maxRetryTimes;
        this.retryWaitTime = retryWaitTime;
        this.baseChooser = baseChooser;
    }

    /**
     * 构建带有重试的选择器
     * @param maxRetryTimes 最大重试次数
     * @param retryWaitTime 每次重试的等待时间(毫秒)
     */
    public RetryChooser(int maxRetryTimes, long retryWaitTime) {
        this(maxRetryTimes, retryWaitTime, new RandomChooser());
    }

    /**
     * 构建带有重试的选择器
     */
    public RetryChooser() {
        this.baseChooser = new RandomChooser();
    }

    @Override
    public Instance choose(Server server) {
        Exception exception;
        try {
            return baseChooser.choose(server);
        } catch (Exception e) {
            exception = e;
        }

        for (int i = 0; i < maxRetryTimes; i++) {
            try {
                TimeUnit.MILLISECONDS.sleep(retryWaitTime);
                return baseChooser.choose(server);
            } catch (Exception e) {
                exception = e;
            }
        }
        throw new NoAvailableServerInstanceException("Server[" + server.name() + "] No Available Instance.", exception);
    }
}